#![allow(non_snake_case)]
use crate::calendar::CalendarItemDate;

use super::PanelVariant;
use chrono::{Datelike, Days, Months, NaiveDate};
use icondata as i;
use leptos::prelude::*;
use leptos_icons::*;
use std::ops::Deref;
use thaw_utils::{now_date, ArcOneCallback};

#[component]
pub fn DatePanel(
    value: RwSignal<Option<NaiveDate>>,
    show_date: RwSignal<NaiveDate>,
    close_panel: ArcOneCallback<Option<NaiveDate>>,
    panel_variant: RwSignal<PanelVariant>,
) -> impl IntoView {
    let dates = Memo::new(move |_| {
        let show_date = show_date.get();
        let show_date_month = show_date.month();
        let mut dates = vec![];

        let mut current_date = show_date;
        let mut current_weekday_number = None::<u32>;
        loop {
            let date = current_date - Days::new(1);
            if date.month() != show_date_month {
                if current_weekday_number.is_none() {
                    current_weekday_number = Some(current_date.weekday().num_days_from_sunday());
                }
                let weekday_number = current_weekday_number.unwrap();
                if weekday_number == 0 {
                    break;
                }
                current_weekday_number = Some(weekday_number - 1);

                dates.push(CalendarItemDate::Previous(date));
            } else {
                dates.push(CalendarItemDate::Current(date));
            }
            current_date = date;
        }
        dates.reverse();
        dates.push(CalendarItemDate::Current(show_date));
        current_date = show_date;
        current_weekday_number = None;
        loop {
            let date = current_date + Days::new(1);
            if date.month() != show_date_month {
                if current_weekday_number.is_none() {
                    current_weekday_number = Some(current_date.weekday().num_days_from_sunday());
                }
                let weekday_number = current_weekday_number.unwrap();
                if weekday_number == 6 {
                    break;
                }
                current_weekday_number = Some(weekday_number + 1);
                dates.push(CalendarItemDate::Next(date));
            } else {
                dates.push(CalendarItemDate::Current(date));
            }
            current_date = date;
        }
        dates
    });
    let previous_year = move |_| {
        show_date.update(|date| {
            *date = *date - Months::new(12);
        });
    };
    let next_year = move |_| {
        show_date.update(|date| {
            *date = *date + Months::new(12);
        });
    };
    let previous_month = move |_| {
        show_date.update(|date| {
            *date = *date - Months::new(1);
        });
    };
    let next_month = move |_| {
        show_date.update(|date| {
            *date = *date + Months::new(1);
        });
    };
    let close_panel1 = close_panel.clone();
    let now = move |_| {
        close_panel1(Some(now_date()));
    };
    let date_items = move || {
        dates
            .get()
            .into_iter()
            .map(|date| {
                let on_click = {
                    let date = date.clone();
                    let close_panel = close_panel.clone();
                    move |_| {
                        close_panel(Some(*date.deref()));
                    }
                };
                view! { <DatePanelItem value date=date on:click=on_click /> }
            })
            .collect_view()
    };
    view! {
        <div class="card w-96 shadow-xl bg-base-100">
            <div class="card-body">
                <div class="card-title flex">
                    <div class="flex-none">
                        <button class="btn btn-ghost btn-sm" on:click=previous_year>
                            <Icon icon=i::AiArrowLeftOutlined />
                        </button>
                        <button class="btn btn-ghost btn-sm" on:click=previous_month>
                            <Icon icon=i::AiLeftOutlined />
                        </button>
                    </div>
                    <div class="flex-1 items-center text-center">
                        <button class="btn btn-ghost btn-sm" on:click=move |_| panel_variant.set(PanelVariant::Year)>
                            <div >{move || show_date.get().year()}年</div>
                        </button>
                        <button class="btn btn-ghost btn-sm" on:click=move |_| panel_variant.set(PanelVariant::Month)>
                            <div>{move || show_date.get().month()}月</div>
                        </button>
                    </div>
                    <div class="flex-none">
                        <button class="btn btn-ghost btn-sm" on:click=next_month>
                            <Icon icon=i::AiRightOutlined />
                        </button>
                        <button class="btn btn-ghost btn-sm" on:click=next_year>
                            <Icon icon=i::AiArrowRightOutlined />
                        </button>
                    </div>
                </div>
                <div class="grid grid-cols-7 gap-2 items-center text-center">
                    <span>"日"</span>
                    <span>"一"</span>
                    <span>"二"</span>
                    <span>"三"</span>
                    <span>"四"</span>
                    <span>"五"</span>
                    <span>"六"</span>
                </div>
                <div class="grid grid-cols-7 gap-2">
                    {date_items}
                </div>
                <div class="card-actions justify-end">
                    <button class="btn btn-outline btn-sm" on:click=now>
                        今天
                    </button>
                </div>
            </div>
        </div>
    }
}

#[component]
fn DatePanelItem(value: RwSignal<Option<NaiveDate>>, date: CalendarItemDate) -> impl IntoView {
    let is_selected = Memo::new({
        let date = date.clone();
        move |_| value.with(|value_date| value_date.as_ref() == Some(date.deref()))
    });

    view! {
        <div
            class="btn btn-ghost btn-sm"
            class=("text-neutral-400",date.is_other_month())
            class=("border-violet-700", move || is_selected.get())
        >
            {date.day()}
        </div>
    }
}
